<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BRow
 *
 * @author jianfeng
 */
class BRow {

    const delimiter = '\\\/.|>';
    const Pattern_Delimiter = "/[.\\/|]/";

    public $attributes = array();
    protected $model = null;
    protected $isLoad = false;
    public $searchableAttributes = array();

    public function getId($data = NULL) {
        $attributes = $this->getAttributes();
        $id = NULL;
        if (is_array($attributes) && isset($attributes['id']))
            $id = $attributes['id'];
        if (is_array($attributes) && isset($attributes['_id']))
            $id = $attributes['_id'];
        return $id;
    }

    public function setId($id) {
        if (is_numeric($id) && $id > 0) {
            $this->attributes['id'] = $id;
            $this->attributes['_id'] = $id;
        }
    }

    public function getName($data = NULL) {
        $attributes = $this->getAttributes();
        $name = NULL;
        if (is_array($attributes) && isset($attributes['name']))
            $name = $attributes['name'];

        return $name;
    }

    /**
     * this function use to get data from database
     * @param type $data
     */
    public function load($data = NULL) {
        $model = $this->getModel();
        if ($model instanceof CActiveRecord) {
            if ($data == NULL) {
                if (isset($this->attributes['id']) && is_numeric($this->attributes['id']) && !is_numeric($data)) {
                    $data = $this->attributes['id'];
                }
                if (isset($this->attributes['_id']) && is_numeric($this->attributes['_id']) && !is_numeric($data)) {
                    $data = $this->attributes['_id'];
                } else {
                    $data = $this->attributes;
                }
            }

            if ($data == NULL)
                return;

            if (is_numeric($data) && $data > 0) {
                $ac = $model->findByPk($data);
                if ($ac instanceof CActiveRecord) {
                    $this->attributes = $ac->attributes;
                    $this->isLoad = TRUE;
                }
            }

            if (is_array($data)) {
                if (isset($data['attributes'])) {//find by attributes
                    $attributes = $data['attributes'];
                    if ($this->searchableAttributes != NULL || !empty($this->searchableAttributes)) {
                        $oAttributes = $attributes;
                        $attributes = array();
                        foreach ($this->searchableAttributes as $name) {
                            if (isset($oAttributes[$name]))
                                $attributes[$name] = $oAttributes[$name];
                        }
                    }
                    $condition = isset($data['condition']) ? $data['condition'] : '';
                    $params = isset($data['params']) ? $data['params'] : array();
                    $ar = $model->findByAttributes($attributes, $condition, $params);
                    if ($ar instanceof CActiveRecord) {
                        $this->attributes = $ar->attributes;
                    }
                    $this->isLoad = TRUE;
                } else if (isset($data['sql'])) {//find by sql
                    $sql = $data['sql'];
                    //$condition = isset($data['condition']) ? $data['condition'] : NULL;
                    $params = isset($data['params']) ? $data['params'] : NULL;
                    $ar = $model->findBySql($sql, $params);
                    if ($ar instanceof CActiveRecord) {
                        $this->attributes = $ar->attributes;
                    }
                    $this->isLoad = TRUE;
                } else {
                    $attributes = $data;
                    $condition = isset($data['condition']) ? $data['condition'] : '';
                    $params = isset($data['params']) ? $data['params'] : array();
                    if ($this->searchableAttributes != NULL || !empty($this->searchableAttributes)) {
                        $oAttributes = $attributes;
                        $attributes = array();
                        foreach ($this->searchableAttributes as $name => $value) {
                            if (isset($oAttributes[$name]))
                                $attributes[$name] = $oAttributes[$name];
                        }
                    }

                    $ar = $model->findByAttributes($attributes, $condition, $params);
                    if ($ar instanceof CActiveRecord) {
                        $this->attributes = $ar->attributes;
                    }
                    $this->isLoad = TRUE;
                }
            }

            //todo-list:maybe need a searchable table for search for row
            //when set attributes in row
            if ($data instanceof BRow) {
                $attributes = $data->attributes;
                if ($this->searchableAttributes != NULL || !empty($this->searchableAttributes)) {
                    $oAttributes = $attributes;
                    $attributes = array();
                    foreach ($this->searchableAttributes as $name) {
                        if (isset($oAttributes[$name]))
                            $attributes[$name] = $oAttributes[$name];
                    }
                }
                $ar = $model->findByAttributes($attributes);
                if ($ar instanceof CActiveRecord) {
                    $this->attributes = $ar->attributes;
                }
                $this->isLoad = TRUE;
            }
        }
    }

    public function save($data = NULL) {
        $model = $this->getModel();
        $attributes = $this->attributes;
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                $attributes[$key] = $value;
            }
        }

        //first try to load
        if ($this->getId() == NULL)
            $this->load($attributes);

        $mRow = new $model();
        if ($this->getId() != NULL && $this->getId() > 0) {
            $mRow = $model->findByPk($this->getId());
        }

        foreach ($attributes as $name => $value) {
            if (!is_string($value) && !is_numeric($value) && $value != NULL) {
                $attributes[$name] = serialize($value);
            }
        }

        $mRow->attributes = $attributes;
        $mRow->save();
        $this->attributes = $mRow->attributes;
    }

    public function getAttributes($data = NULL) {
        $attributes = $this->attributes;
        if (!$this->isLoad)
            $this->load();

        if (!$attributes == NULL)
            $this->attributes += $attributes;

        return $this->attributes;
    }

    public function getAttribute($name) {
        $attributes = $this->getAttributes();
        if (isset($attributes[$name])) {
            return $attributes[$name];
        }
        return FALSE;
    }

    public function getSearchableAttributes($data = NULL) {
        if ($this->searchableAttributes == NULL) {
            $this->searchableAttributes = $this->attributes;
        }
        return $this->searchableAttributes;
    }

    public static function populateFindAttributes($attributes = NULL, $searchableAttributes = array()) {

        /*
          if ($attributes == NULL) {
          $attributes = $this->attributes;
          }
         * 
         */


        if ($searchableAttributes != NULL) {
            $finalAttributes = array();
            foreach ($searchableAttributes as $name) {
                if (isset($attributes[$name]))
                    $finalAttributes[$name] = $attributes[$name];
            }
            return $finalAttributes;
        }
        return $attributes;
    }

    public function setSearchableAttributes($list) {
        $this->searchableAttributes = $list;
    }

    /**
     * 
     * @param type $data
     * @return CActiveRecord
     */
    public function getModel($data = NULL) {
        return $this->model;
    }

    public function getModelClass($data = NULL) {
        $model = $this->getModel();
        if ($model instanceof CActiveRecord)
            return get_class($model);
        if (is_string($model))
            return $model;
    }

    public function setModel($model) {
        if (is_string($model)) {
            $modelClass = $model;
            $this->model = new $modelClass();
        }
        if ($model instanceof CActiveRecord)
            $this->model = $model;
    }

    /**
     * 
     * @param type $recursive
     * @param type $data, specify some condition for children
     * @param type $recursiveItems
     */
    public function getChildren($recursive = FALSE, $data = array(), &$recursiveItems = array()) {
        if ($this->getId() == NULL || !isset($this->attributes['parent_id']))
            return array();

        $children = array();
        if ($data == NULL)
            $data = array();

        $model = $this->getModel();
        if (is_array($data)) {
            if (isset($data['attributes'])) {
                $attributes = $data['attibutes'];
                $attributes['parent_id'] = $this->getId();
                $condition = isset($data['condition']) ? $data['condition'] : NULL;
                $params = isset($data['params']) ? $data['params'] : NULL;
                $rows = $model->findAllByAttributes($attributes, $condition, $params);
                foreach ($rows as $row) {
                    $child = new BRow();
                    $child->attributes = $row->attributes;
                    $child->setModel($model);
                    $children[$child->getId()] = $child;
                }
            } else if (isset($data['sql'])) {
                $sql = $data['sql'];
                $sql .= ' and parent_id=:ParentId';
                $params = isset($data['params']) ? $data['params'] : array();
                $params[':ParentId'] = $this->getId();
                $rows = $model->findAllBySql($sql, $params);
                foreach ($rows as $row) {
                    $child = new BRow();
                    $child->attributes = $row->attributes;
                    $child->setModel($model);
                    $children[$child->getId()] = $child;
                }
            } else {
                $attributes = $data;
                $attributes['parent_id'] = $this->getId();
                if ($attributes != NULL) {
                    $rows = $model->findAllByAttributes($attributes);
                    //$rows = $model->findAllByAttributes($attributes);
                    foreach ($rows as $row) {
                        $child = new BRow();
                        $child->attributes = $row->attributes;
                        $child->setModel($model);
                        $children[$child->getId()] = $child;
                    }
                }
            }
        }
        if ($data instanceof BRow) {
            $attributes = $data->attributes;
            $attributes['parent_id'] = $this->getId();
            if ($attributes != NULL) {
                $rows = $model->findAllByAttributes($attributes);
                //$rows = $model->findAllByAttributes($attributes);
                foreach ($rows as $row) {
                    $child = new BRow();
                    $child->attributes = $row->attributes;
                    $child->setModel($model);
                    $children[$child->getId()] = $child;
                }
            }
        }

        if ($recursive) {
            $recursiveItems = $recursiveItems + $children;
            foreach ($children as $child) {
                $child->getChildren($recursive, $data, $recursiveItems);
            }
            $children = $recursiveItems;
        }

        /*
          if ($children != NULL) {
          foreach ($children as &$child) {
          $child->setSearchableAttributes($this->getSearchableAttributes());
          }
          }
         * 
         */

        return $children;
    }

    public function getParent($recursive = FALSE, $data = NULL, &$recursiveItems = array()) {
        if ($this->getId() == NULL || !isset($this->attributes['parent_id']))
            return FALSE;

        $parentId = $this->attributes['parent_id'];
        $parent = NULL;
        //$parents = array();
        if (is_numeric($parentId) && $parentId > 0) {
            $model = $this->getModel();
            $row = $model->findByPk($parentId);
            $parent = new BRow();
            $parent->attributes = $row->attributes;
            $parent->setModel($model);
//            return $parent;
        }

        if ($recursive) {
            if ($parent != NULL && $parent->getId() != NULL && $parent->getId() != 1) {
                $recursiveItems[$parent->getId()] = $parent;

                //if ($parent->attributes['parent_id'] > 0)
                $parent->getParent($recursive, $data, $recursiveItems);
            }
            return $recursiveItems;
        }

        return $parent;
    }

    /**
     * support nested child
     * @param type $data
     */
    public function getChild($data = NULL, $recursive = FALSE) {
        $split_pattern = '/[.|\\/]/';

        if (is_numeric($data)) {
            $id = $data;
            $row = new BRow();
            $row->setModel($this->getModel());
            $row->setSearchableAttributes($this->getSearchableAttributes());
            $row->load($data);
            if (isset($row->attributes['parent_id']) && $row->attributes['parent_id'] == $this->getId())
                return $row;
            return false;
        }

        if (is_string($data)) {
            $name = $data;
            $data = array();
            $data['name'] = $name;
        }

        if ($data instanceof BRow) {
            $data = $data->attributes;
        }

        if (is_array($data) && isset($data['name'])) {
            if ($data['name'] != NULL) {
                $name = $data['name'];
                $names = preg_split($split_pattern, $name);
                $count = count($names);
                $i = 0;
                if ($count > 1) {
                    $parent = $this;
                    foreach ($names as $n) {
                        $tempData = $data;
                        $tempData['name'] = $n;
                        $children = $parent->getChildren(FALSE, $tempData);
                        foreach ($children as $child) {
                            if ($child->getName() == $n) {
                                $parent = $child;
                                $i++;
                                break;
                            }
                        }
                    }
                    if ($i == $count) {
                        $parent->setSearchableAttributes($this->getSearchableAttributes());
                        return $parent;
                    }
                    return false;
                }
            }
        }

        $children = $this->getChildren(FALSE, $data);
        if (!empty($children)) {
            $child = reset($children);
            $child->setSearchableAttributes($this->getSearchableAttributes());
            return $child;
        }

        return FALSE;
    }

    public function addChild($data = NULL) {
        // $model = $this->getModel();

        if (is_string($data)) {
            $name = $data;
            $data = new BRow();
            $data->attributes['name'] = $name;
            $data->setModel($this->getModel());
            $data->setSearchableAttributes($this->getSearchableAttributes());
        }

        if (is_array($data)) {
            $attributes = $data;
            $data = new BRow();
            $data->setModel($this->getModel());
            $data->attributes = $attributes;
            $data->setSearchableAttributes($this->getSearchableAttributes());
            //find item first, if find, no need crate new item
            //$data->load();
        }

        if ($data instanceof BRow) {
            $childRow = $data;
            $childRow->setModel($this->getModel());
            //$childRow->load();
            //if ($childRow->getId() != NULL && $childRow->getId() > 0) {
            //if find childRow, just add it as child
            //$childRow->attributes['parent_id'] = $this->getId();
            //$childRow->save();
            //return $childRow;
            //}
            //$model = $this->getModel();
            //support save nested name of row
            if (isset($childRow->attributes['name']))
                $name = $childRow->attributes['name'];
            //$name = $childRow->getName();
            if ($name != NULL) {
                $names = preg_split(BTreeEntity::Pattern_Delimiter, $name);
                $count = count($names);
                if ($count > 0) {
                    $parentRow = $this;
                    $count = count($names);
                    $i = 0;
                    $fullName = $this->attributes['fullname'];
                    if ($fullName == 'root')
                        $fullName = NULL;
                    foreach ($names as $n) {
                        $i++;
                        if ($fullName == NULL)
                            $fullName = $n;
                        else {
                            $fullName .= '.' . $n;
                        }
                        $newChildRow = clone $childRow;
                        $newChildRow->attributes['_id'] = NULL;
                        $newChildRow->attributes['name'] = $n;
                        $newChildRow->attributes['fullname'] = $fullName;
                        $newChildRow->attributes['parent_id'] = $parentRow->getId();
                        if ($i < $count) {
                            if (isset($newChildRow->attributes['value'])) {
                                $newChildRow->attributes['value'] = null;
                            }
                        }
                        $newChildRow->load();
                        if ($newChildRow->getId() == NULL)
                            $newChildRow->save();
                        if (isset($newChildRow->attributes['parent_id']) && $newChildRow->attributes['parent_id'] == $parentRow->getId())
                            $parentRow = $newChildRow;
                        else {
                            $newChildRow->attributes['parent_id'] = $parentRow->getId();
                            $newChildRow->save();
                            $parentRow = $newChildRow;
                        }
                    }
                    if ($count == $i)
                        return $parentRow;
                }
            }
        }
    }

    public function getFullName($spliter = '|', $stringFormat = true) {
        $parents = $this->getParent(TRUE);
        if ($parents != NULL) {
            $names = array();
            foreach ($parents as $row) {
                if ($row->getName() != 'root') {
                    array_push($names, $row->getName());
                }
            }
            array_reverse($names);
            $fName = '';
            foreach ($names as $name) {
                if ($fName == '')
                    $fName = $name;
                else
                    $fName.=$spliter . $name;
            }
            if ($stringFormat)
                return $fName;
            else
                return $names;
        }
        return $this->getName();
    }

    /**
     * if use id as member primary key, can use this function to connect member
     * @param BRow $memberContext
     * @param type $memberModelContext
     * @param BRow $member2Context
     */
    public function addMember($memberContext, $member2Context = NULL, $memberModelContext = array()) {

        if ($memberContext instanceof BRow) {
            $myMemberCol = $this->populateMyMemberCol();
            if (is_array($memberModelContext)) {
                if (isset($memberModelContext['myMemberCol'])) {
                    $myMemberCol = $memberModelContext['myMemberCol'];
                    unset($memberModelContext['myMemberCol']);
                }
            }
            $memberModel = $this->populateMemberModel($memberContext);
            if (is_array($memberModelContext)) {
                if (isset($memberModelContext['memberModel'])) {
                    $memberModel = $memberModelContext['memberModel'];
                    unset($memberModelContext['memberModel']);
                }
            }
            $memberCol = $this->populateMemberCol($memberContext);
            if (is_array($memberModelContext)) {
                if (isset($memberModelContext['memberCol'])) {
                    $memberCol = $memberModelContext['memberCole'];
                    unset($memberModelContext['memberCol']);
                }
            }
            $memberId = $memberContext->getId();
            $member2Col = NULL;
            $member2Id = NULL;
            if ($member2Context instanceof BRow) {
                $memberModel = $this->populateMemberModel($memberContext, $member2Context);
                $member2Col = $this->populateMemberCol($member2Context, $memberModel);
                $member2Id = $member2Context->getId();
                if (is_array($memberModelContext)) {
                    if (isset($memberModelContext['member2Col'])) {
                        $member2Col = $memberModelContext['member2Col'];
                        unset($memberModelContext['member2Col']);
                    }
                }
            }

            $attributes = array();
            if (is_string($memberModel))
                $memberModel = new $memberModel();
            if ($memberModel instanceof CActiveRecord) {
                if ($myMemberCol != NULL && $this->getId() != null) {
                    $attributes[$myMemberCol] = $this->getId();
                }
                $modelClass = get_class($memberModel);
                if (strpos($modelClass, 'GroupMember') && isset($memberModel->group_class)) {
                    $attributes['group_class'] = $this->getModelClass();
                }

                if ($memberCol != NULL && $memberId != null)
                    $attributes[$memberCol] = $memberId;

                if ($member2Col != NULL && $member2Id != NULL)
                    $attributes[$member2Col] = $member2Id;
            }

            if (isset($attributes['member_id']) && isset($memberModel->group_class)) {
                $attributes['member_class'] = $memberContext->getModelClass();
            }

            if (is_array($memberModelContext)) {
                foreach ($memberModelContext as $key => $value) {
                    $attributes[$key] = $value;
                }
            }

            $mRow = $memberModel->findByAttributes($attributes);

            if (!$mRow instanceof CActiveRecord) {
                $mRow = new $memberModel();
                $mRow->attributes = $attributes;
                $mRow->save();
            }
        }
    }

    public function getMember($member1Context = array(), $member2Context = array(), $returnIndex = 1) {
        $members = $this->getMembers($member1Context, $member2Context, $returnIndex);
        return reset($members);
        //Freturn FALSE;
    }

    /**
     * 
     * @param BRow $member1Context, row for member1
     * @param BRow $member2Context, row for member2
     * @param type $returnIndex
     * @return \BRow
     */
    public function getMembers($member1Context = array(), $member2Context = array(), $returnIndex = 1) {

        //$groupRow = $this;
        $member1Row = NULL;
        $member2Row = NULL;
        $attributes = array();
        $groupCol = null;
        $member1Col = NULL;
        $member2Col = NULL;

        if ($member1Context instanceof BRow)
            $member1Row = $member1Context;

        if ($member2Context instanceof BRow)
            $member2Row = $member2Context;

        $groupMemberModelClass = $this->populateMemberModel($member1Row);

        if ($member2Row != NULL)
            $groupMemberModelClass = $this->populateMemberModel($member2Row, $member2Row);

        if ($this->getId() != NULL) {
            $groupCol = $this->populateMyMemberCol();
            $attributes[$groupCol] = $this->getId();
        }

        if ($member1Row instanceof BRow)
            $member1Col = $this->populateMemberCol($member1Row);

        if ($member1Row->getId() != NULL) {
            $attributes[$member1Col] = $member1Row->getId();
        }

        if ($member2Row instanceof BRow)
            $member2Col = $this->populateMemberCol($member2Row);

        if ($member2Row != NULL && $member2Row->getId() != NULL) {
            $member2Col = $this->populateMemberCol($member2Row);
            $attributes[$member2Col] = $member2Row->getId();
        }

        $arList = $groupMemberModelClass::model()->findAllByAttributes($attributes);

        //return member1List
        if ($returnIndex == 1) {
            $member1List = array();
            foreach ($arList as $ar) {
                $row = new BRow();
                $row->setModel($member1Row->getModel());
                $row->load($ar->attributes[$member1Col]);
                $member1List[$row->getId()] = $row;
            }
            return $member1List;
        }

        //return member1List
        if ($returnIndex == 2) {
            $member2List = array();
            foreach ($arList as $ar) {
                $row = new BRow();
                $row->setModel($member2Row->getModel());
                $row->load($ar->attributes[$member2Col]);
                $member2List[$row->getId()] = $row;
            }
            return $member2List;
        }
    }

    public function removeMember($memberContext, $data = NULL) {
        if ($memberContext instanceof BRow) {
            $groupMemberModel = $this->populateMemberModel($memberContext);
            $memberCol = $this->populateMemberCol($memberContext);
            $myMemberCol = $this->populateMyMemberCol();
            $attributes = array();
            if ($memberContext->getId() != NULL) {
                $attributes[$myMemberCol] = $this->getId();
                $attributes[$memberCol] = $memberContext->getId();
                $ar = $groupMemberModel::findByAttribute($attributes);
                if ($ar instanceof CActiveRecord)
                    return $ar->delete();
            }
        }
        return FALSE;
    }

    /**
     * 
     * @param type $memberContext, row for member2 if exist
     * @param array $groupContext, can be row for group,or modelClass for group
     * if not set, use default group model class
     * @param type $context
     */
    public function getGroups($groupContext = null, $memberContext = null, $context = NULL) {

        $member2Row = NULL;
        $member1Row = $this;
        $groupModelClass = NULL;
        $groupRow = new BRow;
        if ($memberContext instanceof BRow) {
            $member2Row = $memberContext;
        }

        if ($groupContext == NULL) {
            $groupModelClass = $this->getModelClass() . 'Group';
            $groupRow->setModel($groupModelClass);
        }
        if (is_string($groupContext)) {
            $groupModelClass = $groupContext;
            $groupRow->setModel($groupModelClass);
        }

        if ($groupContext instanceof BRow) {
            $groupRow = $groupContext;
            $groupModelClass = $groupContext->getModelClass();
        }

        if ($groupRow instanceof BRow) {
            $groupMemberModelClass = $groupRow->populateMemberModel($member1Row, $member2Row);
            $groupCol = $groupRow->populateMyMemberCol();
            $member1Col = $groupRow->populateMemberCol($member1Row);
            $member2Col = NULL;
            if ($member2Row instanceof BRow)
                $member2Col = $groupRow->populateMemberCol($member2Row);

            $attributes = array();
            if ($member1Col != NULL && $member1Row->getId() != NULL) {
                $attributes[$member1Col] = $member1Row->getId();
            }
            if ($member2Col != NULL && $member2Row != NULL && $member2Row->getId() != NULL) {
                $attributes[$member2Col] = $member2Row->getId();
            }

            $arList = $groupMemberModelClass::model()->findAllByAttributes($attributes);

            $groupRowList = array();
            foreach ($arList as $ar) {
                $groupRow = new BRow();
                $groupRow->setModel($groupModelClass);
                $id = $ar->attributes[$groupCol];
                $groupRow->load($id);
                $groupRowList[$id] = $groupRow;
            }
            return $groupRowList;
        }
    }

    public function delete($data = NULL) {
        $model = $this->getModel();
        $ar = $model->findByPk($this->getId());
        if ($ar instanceof CActiveRecord)
            return $ar->delete();
    }

    public function getChildrenAsLeaf($context = null, $parent = NULL, &$recursiveItems = array()) {
        if ($parent == NULL)
            $parent = $this;

        if (!$parent->isTreeRow())
            return;

        //$leafChildren = array();
        $children = $this->getChildren($context);
        foreach ($children as $id => $child) {
            if (!$child->hasChild()) {
                $recursiveItems[$id] = $child;
            } else {
                $child->getChildrenAsLeaf($context, NULL, $recursiveItems);
            }
        }
        return $recursiveItems;
    }

    public function hasChild($context = NULL) {
        $children = $this->getChildren($context);
        if (!empty($children))
            return TRUE;
        return FALSE;
    }

    public function isTreeRow($data = NULL) {
        $attributes = $this->getAttributes();
        if (isset($attributes['parent_id']))
            return TRUE;
        return FALSE;
    }

    protected function populateMemberCol($memberContext, $memberModel = null) {

        if ($memberModel == null) {
            $memberModel = $this->populateMemberModel($memberContext);
        }

        if (is_string($memberModel)) {
            $memberModelClass = $memberModel;
            $memberModel = new $memberModelClass();
        }

        if ($memberModel instanceof CActiveRecord && $memberContext instanceof BRow) {
            $model = $memberContext->getModel();
            $modelClass = NULL;
            if (is_string($model))
                $modelClass = $model;
            if ($model instanceof CActiveRecord)
                $modelClass = get_class($model);

            $attributes = $memberModel->getAttributes();
            if (array_key_exists('member_id', $attributes))
                return 'member_id';
            else {
                if ($modelClass != NULL) {
                    $matches = array();
                    preg_match("/^[A-Z]*/", $modelClass, $matches);
                    $firstBigLetters = $matches[0];
                    $count = strlen($firstBigLetters);
                    $member_col = strtolower(substr($modelClass, $count - 1));
                    $member_col .= '_id';
                    if (isset($attributes[$member_col]))
                        return $member_col;
                }
            }
        }

        return false;
    }

    protected function populateMyMemberCol($data = NULL) {

        $modelClass = $this->getModelClass();

        if (strpos(strtolower($modelClass), 'group') !== FALSE)
            return 'group_id';

        if ($modelClass != NULL) {
            $matches = array();
            preg_match("/^[A-Z]*/", $modelClass, $matches);
            $firstBigLetters = $matches[0];
            $count = strlen($firstBigLetters);
            $member_col = strtolower(substr($modelClass, $count - 1));
            $member_col .= '_id';

            return $member_col;
        }

        return false;
    }

    /**
     * 
     * @param BRow $memberContext
     * @param BRow $member2Context
     * @return boolean
     */
    public function populateMemberModel($memberContext, $member2Context = NULL) {

        $myModelClass = $this->getModelClass();

        if (strpos($myModelClass, 'Group') > 1)
            return $myModelClass . 'Member';

        if ($memberContext instanceof BRow) {
            $model = $memberContext->getModel();
            $modelClass = NULL;
            if (is_string($model))
                $modelClass = $model;
            if ($model instanceof CActiveRecord)
                $modelClass = get_class($model);

            if ($modelClass != NULL) {
                $matches = array();
                $firstBigLetters = preg_match("/^[A-Z]*/", $modelClass, $matches);
                if ($firstBigLetters != NULL) {
                    $count = strlen($matches[0]);
                    $memberClass = substr($modelClass, $count - 1);
                    $memberModelClass = $myModelClass . $memberClass;
                }
            }
        }

        if ($member2Context instanceof BRow) {
            $model = $member2Context->getModel();
            $modelClass = NULL;
            if (is_string($model))
                $modelClass = $model;
            if ($model instanceof CActiveRecord)
                $modelClass = get_class($model);

            if ($modelClass != NULL) {
                $matches = array();
                $firstBigLetters = preg_match("/^[A-Z]*/", $modelClass, $matches);
                if ($firstBigLetters != NULL) {
                    $count = strlen($matches[0]);
                    $memberClass = substr($modelClass, $count - 1);
                    $memberModelClass .= $memberClass;
                }
            }
        }

        if (class_exists($memberModelClass))
            return $memberModelClass;

        return false;
    }

}
